package com.yjb.demo.shardingjdbc.config.shardingjdbc;

import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;

import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

/**
 * @description 
 * @author yinjinbiao
 * @create 2024/1/5 11:04
 * @version 1.0
 */
@Slf4j
@Component(value = "dbShardingAlgorithm")
public class DbShardingAlgorithm implements StandardShardingAlgorithm<String> {

	/**
	 * 分片算法的属性配置
	 */
	private final Properties properties = new Properties();

	/**
	 * 分片键参数格式化
	 */
	private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	/**
	 * 根据精确分片值进行分片操作，返回分片后的目标库名
	 *
	 * @param collection           所有的目标库名集合
	 * @param preciseShardingValue 精确分片值对象，包含了逻辑库名、分片键和分片值
	 * @return 分片后的目标库名
	 */
	@Override
	public String doSharding(final Collection collection, final PreciseShardingValue preciseShardingValue) {
		String year = preciseShardingValue.getValue().toString();
		String target = "";
		for (Object o : collection) {
			if (o.toString().contains(String.valueOf(year))) {
				target = o.toString();
			}
		}
		return target;
	}

	/**
	 * 根据范围分片值进行分片操作，返回分片后的目标库名集合
	 *
	 * @param collection         所有的目标库名集合
	 * @param rangeShardingValue 范围分片值对象，包含了逻辑库名、分片键和分片范围
	 * @return 分片后的目标库名集合
	 */
	@Override
	public Collection<String> doSharding(final Collection<String> collection,
	                                     final RangeShardingValue<String> rangeShardingValue) {
		Range<String> valueRange = rangeShardingValue.getValueRange();
		// 如果其中一个限制为空，则遍历所有表
		if (!(valueRange.hasUpperBound()&&valueRange.hasLowerBound())){
			return collection;
		}
		Set<String> resultSet = new HashSet<>();
		Long lower = Long.valueOf(valueRange.lowerEndpoint());
		Long upper = Long.valueOf(valueRange.upperEndpoint());

		while (lower<upper) {
			for (Object o : collection) {
				if (o.toString().contains(String.valueOf(lower))) {
					resultSet.add(o.toString());
				}
			}
			lower++;
		}
		return resultSet;
	}

	/**
	 * 获取分片算法的类型
	 *
	 * @return 分片算法的类型
	 */
	@Override
	public String getType() {
		return "DB_SHARDING_BY_YEAR";
	}

	/**
	 * 获取分片算法的属性配置
	 *
	 * @return 分片算法的属性配置
	 */
	@Override
	public Properties getProps() {
		return properties;
	}

	/**
	 * 初始化分片算法和属性配置
	 *
	 * @param properties 分片算法的属性配置
	 */
	@Override
	public void init(Properties properties) {
		log.info("初始化按年分库算法 -> properties:{}", properties.toString());
	}
}
